import {Boundary} from "../map/boundary.mjs";

function meshgrid(arr) {
    return arr.map(i => arr.map(j => [i, j]))  //.flat()
}

function diff(A, B) {
    [A, B] = [A.flat(), B.flat()]
    return A.filter(a => B.every(b => !(a[0] === b[0] && a[1] === b[1])));
}

export class Player {
    #offsets
    #keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']

    constructor(x, y, gameMap) {
        this.#offsets = meshgrid([-1, 0, 1])
        this.pos = [x, y]
        this.peekArray = this.getPeekArray(x, y)

        // this.tileArray = tileArray
        this.gameMap = gameMap
        gameMap.initState(this.peekArray)
        this.boundary = new Boundary(gameMap.mapSize)
    }

    setEventListener() {
        let nextPos = this.nextPos.bind(this)
        window.addEventListener('keydown', nextPos)
    }

    #nextPos(key) {
        switch (key) {
            case 'ArrowUp':
                this.pos[0]--
                return
            case 'ArrowLeft':
                this.pos[1]--
                return
            case 'ArrowDown':
                this.pos[0]++
                return
            case 'ArrowRight':
                this.pos[1]++
                return
        }
    }

    nextPos(event) {
        let key = event.key
        if (!this.#keys.includes(key) || this.boundary.on(key))
            return

        this.gameMap.removeState(this.pos, 'cloaked', 'peek', 'player')
        this.#nextPos(key)
        this.gameMap.addState(this.pos, 'player')

        let newPeekArray = this.getPeekArray(...this.pos)
        let leavingPoints = diff(this.peekArray, newPeekArray)
        let enteringPoints = diff(newPeekArray, this.peekArray)

        this.gameMap.removeState(leavingPoints, 'peek')
        this.gameMap.addState(enteringPoints, 'peek')

        this.peekArray = newPeekArray

        this.boundary.reset(this.pos)
    }

    getPeekArray(x, y) {
        return this.#offsets.map(row =>
            row.map(([x_off, y_off]) => [x + x_off, y + y_off]))
    }
}
